package at.fhooe.engine.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import at.fhooe.engine.event.events.EntityCreatedEvent;
import at.fhooe.engine.event.events.EntityDestroyedEvent;
import at.fhooe.engine.pandora.Game;

public class EntityManager {

	private HashMap<String, Entity> m_entities;
	private ArrayList<Entity> m_entitiesToEngage;
	private ArrayList<Entity> m_entitiesToDisengage;
	
	public EntityManager() {
		m_entities = new HashMap<String, Entity>();
		m_entitiesToEngage = new ArrayList<Entity>();
		m_entitiesToDisengage = new ArrayList<Entity>();
	}
	
	public synchronized void update() {
		for(Entity entity: m_entitiesToEngage) {
			Game.getInstance().getEventManager().dispatchEvent(new EntityCreatedEvent(entity.getEntityId(), entity.getName()));
		
			entity.engage();
			m_entities.put(entity.getName(), entity);
		}
		m_entitiesToEngage.clear();
		
		for(Entity entity: m_entitiesToDisengage) {
			Game.getInstance().getEventManager().dispatchEvent(new EntityDestroyedEvent(entity.getEntityId(), entity.getName()));
			
			entity.disengage();
			m_entities.remove(entity.getName());
		}
		m_entitiesToDisengage.clear();
		
		for (Entity entity : m_entities.values()) {
			entity.update();
		}
	}
	
	public synchronized void addEntity(Entity entity) {
		if(	hasEntity(entity.getName())) {
			throw new RuntimeException("Entity with name: '" + entity.getName() + "' exists already.");
		} 
		if(m_entitiesToEngage.contains(entity)) {
			throw new RuntimeException("Entity with name: '" + entity.getName() + "' was already added.");
		}
		m_entitiesToEngage.add(entity);
	}
	
	public synchronized void removeEntity(Entity entity) {
		m_entitiesToDisengage.add(entity);
	}
	
	public synchronized void removeEntity(String name) {
		Entity entity = getEntity(name);
		removeEntity(entity);
	}
	
	public synchronized void removeAllEntities() {
		for(Entity entity: m_entities.values()) {
			removeEntity(entity);
		}
	}
	
	public synchronized boolean hasEntity(String name) {
		return m_entities.containsKey(name);
	}
	
	public synchronized boolean hasEntityWithId(String entityId) {
		Iterator<Map.Entry<String, Entity>> it = m_entities.entrySet().iterator();
		while (it.hasNext()) {
			Entity entity = ((Map.Entry<String, Entity>)it.next()).getValue();
			if (entity.getEntityId().compareTo(entityId) == 0)
				return true;
		}

		return false;
	}
	
	public synchronized Entity getEntity(String name) {
		Entity entity = m_entities.get(name);
		
		return entity;
	}
	
	public ArrayList<Entity> getEntitiesWithId(String entityId) {
		ArrayList<Entity> foundEntities = new ArrayList<Entity>();
		
		Iterator<Map.Entry<String, Entity>> it = m_entities.entrySet().iterator();
		while (it.hasNext()) {
			Entity entity = ((Map.Entry<String, Entity>)it.next()).getValue();
			if (entity.getEntityId().compareTo(entityId) == 0)
				foundEntities.add(entity);
		}
		
		return foundEntities;
	}

	public int getEntityCount() {
		return m_entities.size();
	}
	
	public void clearEntitiesToEngage() {
		m_entitiesToEngage.clear();
	}

	public Entity getEntityWithId(String entityId) {
		Iterator<Map.Entry<String, Entity>> it = m_entities.entrySet().iterator();
		while (it.hasNext()) {
			Entity entity = ((Map.Entry<String, Entity>)it.next()).getValue();
			if (entity.getEntityId().compareTo(entityId) == 0)
				return entity;
		}
		return null;
	}
}
